package org.carl.component.job.util

import org.carl.component.job.constant.PlatForm
import java.sql.Timestamp
import java.text.ParseException
import java.text.SimpleDateFormat
import java.time.*
import java.util.*

/**
 * email carl.chen@bk.ru
 * @Author: 陈青松
 * @Date: 2019/1/20 21:12
 */
class CronUtils {

    companion object {

        /**
         * 功能描述：日期转换cron表达式
         */
        fun formatDateByPattern(date: Date): String {
            return PlatForm.CRON_DATE_FORMAT.format(date)
        }

        /***
         * convert Date to cron, eg "0 07 10 15 1 ? 2016"
         * @param date  : 时间点
         * @return
         */
        fun getCron(data: Date): String {
            return formatDateByPattern(data)
        }

        /**
         * 将时间转换为时间戳
         */
        fun dateToStamp(date: Date): Timestamp {
            return Timestamp(date.time)
        }

        /**
         * 将时间戳转换为时间
         */
        fun stampToDate(ts: Timestamp): Date {
            return Date(ts.time)
        }

        /**
         * 获得某天最大时间 2017-10-15 23:59:59
         *
         * @param date Date某个时间
         * @return Date 调整过的时间
         */
        fun getEndOfDay(date: Date): Date {
            val localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.time), ZoneId.systemDefault())
            val endOfDay = localDateTime.with(LocalTime.MAX)
            return Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant())
        }

        /**
         * 获取结束时间
         *
         * @param date String
         * @return
         */
        fun getEndOfDay(date: String): Date {
            val localDateTime = toLocalDateTime(getDate(date))
            val endOfDay = localDateTime.with(LocalTime.MAX)
            return Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant())
        }

        /**
         * 获得字符串类型的结束时间23:59:59
         *
         * @param date String 转换前时间
         * @return String 转换后时间
         */
        fun getStrEndOfDay(date: String): String {
            val localDateTime = toLocalDateTime(getDate(date))
            val endOfDay = localDateTime.with(LocalTime.MAX)
            return PlatForm.LONG_DATE_FORMAT.format(toDate(endOfDay))
        }

        /**
         * 获取长类型字符串
         *
         * @param date String
         * @return String
         */
        fun getLongDate(date: String): String {
            val newDate = getDate(date)
            return PlatForm.LONG_DATE_FORMAT.format(newDate)
        }

        /**
         * 获取短类型字符串
         *
         * @param date String
         * @return String
         */
        fun getShortDate(date: String): String {
            val newDate = getDate(date)
            return PlatForm.SHORT_DATE_FORMAT.format(newDate)
        }

        /**
         * 获得某天最小时间 2017-10-15 00:00:00
         *
         * @param date Date某个时间
         * @return Date 调整过的时间
         */
        fun getStartOfDay(date: Date): Date {
            val localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.time), ZoneId.systemDefault())
            val startOfDay = localDateTime.with(LocalTime.MIN)
            return Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant())
        }

        /**
         * 获得某天最小时间 2017-10-15 00:00:00
         *
         * @param date String 时间
         * @return
         */
        fun getStartOfDay(date: String): Date {
            val localDateTime = toLocalDateTime(getDate(date))
            val startOfDay = localDateTime.with(LocalTime.MIN)
            return Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant())
        }

        /**
         * 获取字符串类型的含有00:00:01的时间
         *
         * @param date String
         * @return String
         */
        fun getStrStartOfDay(date: String): String {
            val localDateTime = toLocalDateTime(getDate(date))
            val startOfDay = localDateTime.with(LocalTime.MIN)
            return PlatForm.LONG_DATE_FORMAT.format(toDate(startOfDay))
        }

        /**
         * 格式化时间
         * @param date
         * @return
         */
        fun toLongDate(date: Date): String {
            return PlatForm.LONG_DATE_FORMAT.format(date)
        }

        /**
         * LocalDateTime 转Date
         *
         * @param localDateTime LocalDateTime
         * @return Date
         */
        fun toDate(localDateTime: LocalDateTime): Date {
            val zone = ZoneId.systemDefault()
            val instant = localDateTime.atZone(zone).toInstant()
            return Date.from(instant)
        }

        /**
         * Date转LocalDateTime
         *
         * @param date Date
         * @return LocalDateTime
         */
        fun toLocalDateTime(date: Date): LocalDateTime {
            val instant = date.toInstant()
            val zone = ZoneId.systemDefault()
            return LocalDateTime.ofInstant(instant, zone)
        }

        /**
         * 获取时间支持纯数字及长短两种类型
         *
         * @param date
         * @return
         */
        fun getDate(date: String): Date {
            try {
                if (date.matches("\\d+".toRegex())) {
                    return Date(java.lang.Long.valueOf(date))
                }
                return if (date.contains(" ")) {
                    PlatForm.LONG_DATE_FORMAT.parse(date)
                } else {
                    PlatForm.SHORT_DATE_FORMAT.parse(date)
                }
            } catch (e: ParseException) {
                throw RuntimeException(e)
            }

        }

        private val sdf = SimpleDateFormat("ss mm HH dd MM ? yyyy")

        /**
         * LocalDateTime 获取 时间戳
         * @param localDateTime
         * @return
         */
        fun getMillisByLocalDateTime(localDateTime: LocalDateTime): Long {
            return localDateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli()
        }

        /**
         * LocalDate 获取 时间戳
         * @param localDate
         * @return
         */
        fun getMillisByLocalDate(localDate: LocalDate): Long {
            return localDate.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli()
        }

        /**
         * 根据时间戳获取当前时间，
         * @param times
         * @return
         */
        fun getLocalDateByLongTime(times: Long?): LocalDate {
            val instant = Instant.ofEpochMilli(times!!)
            // 获取系统默认时区
            val zoneId = ZoneId.systemDefault()
            return LocalDateTime.ofInstant(instant, zoneId).toLocalDate()
        }

        /**
         * 根据时间戳获取当前时间，
         * @param timestamp
         * @return
         */
        fun getLocalDateTimeByLongTime(timestamp: Long?): LocalDateTime {
            return Instant.ofEpochMilli(timestamp!!).atZone(ZoneId.systemDefault()).toLocalDateTime()
        }
    }
}